package github.sf.fw.utils;

import java.math.BigDecimal;
import java.util.List;

/**
 * 计算帮助类
 *
 * @author zhoup
 */
public class ScopeUtils {
    /**
     * 区间判断
     *
     * @param a          待判断的值
     * @param left       区间左值
     * @param right      区间右值
     * @param leftEqual  左边是否为闭区间
     * @param rightEqual 右边是否为闭区间
     * @return a是否在传入的区间内
     */
    public static boolean inSection(Number a, Number left, Number right, boolean leftEqual, boolean rightEqual) {
        if (left.doubleValue() > right.doubleValue()) {
            return inSection(a, right, left, leftEqual, rightEqual);
        }
        boolean r;
        if (leftEqual) {
            r = a.doubleValue() >= left.doubleValue();
        } else {
            r = a.doubleValue() > left.doubleValue();
        }
        if (rightEqual) {
            r = a.doubleValue() <= right.doubleValue() && r;
        } else {
            r = a.doubleValue() < right.doubleValue() && r;
        }
        return r;
    }

    /**
     * a是否在闭区间内
     */
    public static boolean closedInterval(Number a, Number left, Number right) {
        return inSection(a, left, right, true, true);
    }

    /**
     * a是否在闭区间内，left和right的顺序可忽略，程序会自己判断
     */
    public static boolean ignoreClosedInterval(Number a, Number left, Number right) {
        if (left.doubleValue() < right.doubleValue()) {
            return inSection(a, left, right, true, true);
        } else {
            return inSection(a, right, left, true, true);
        }
    }

    /**
     * a是否在开区间内
     */
    public static boolean openInterval(Number a, Number left, Number right) {
        return inSection(a, left, right, false, false);
    }

    /**
     * n是否在base的±offset闭区间范围内
     */
    public static boolean intervalOfOffset(Number n, Number base, Number offset) {
        BigDecimal baseDecimal = BigDecimal.valueOf(base.doubleValue());
        BigDecimal offsetDecimal = BigDecimal.valueOf(offset.doubleValue());
        BigDecimal left = baseDecimal.subtract(offsetDecimal);
        BigDecimal right = baseDecimal.add(offsetDecimal);
        return closedInterval(n, left, right);
    }

    /**
     * n是否在base的±offset闭区间范围内
     */
    public static boolean intervalOfOffset(Number n, Number base, BigDecimal offset) {
        BigDecimal baseDecimal = BigDecimal.valueOf(base.doubleValue());
        BigDecimal left = baseDecimal.subtract(offset);
        BigDecimal right = baseDecimal.add(offset);
        return closedInterval(n, left, right);
    }

    /**
     * n是否在bases数组的中的每个数字的±offset闭区间范围内
     *
     * @param bases  基本数列
     * @param n      待判断的数字
     * @param offset 偏移
     * @return 数字n是否在基本数列的偏移量范围内
     */
    public static boolean intervalOfList(List<? extends Number> bases, Number n, Number offset) {
        BigDecimal offsetDecimal = BigDecimal.valueOf(offset.doubleValue());
        for (Number base : bases) {
            if (intervalOfOffset(n, base, offsetDecimal)) {
                return true;
            }
        }
        return false;
    }
}
